/**
 * \file lcd.c
 * \brief Driver LCD.
 * \author Nicolas.M
 * \version 0.13
 * \date 22 février 2011
 *
 * Fichier d'implémentation des APIs de l'écran LCD.
 *
 */
 
#include <msp430x14x.h>
#include "lcd.h"

#include "../utils/utils.h"
#include <stdio.h>
#include <string.h>

/**
 *\def		LCD_Data           
 *\def     RS                
 * P2.2
 *\def     E                 
 * P2.3
 *\def		DISP_ON			
 * LCD control constants
 *\def		DISP_OFF		
 *\def		CLR_DISP		
 *\def		WRITE_0_DDRAM_ADDRESS	
 *\def 	WRITE_40_DDRAM_ADDRESS	
 *\def		WRITE_DDRAM_ADDRESS
 *\def		WRITE_DDRAM		
 */
 

#define		LCD_Data           P2OUT
#define     RS                 2                 //P2.2
#define     E                  3                 //P2.3
#define		DISP_ON			0x0c	        //LCD control constants
#define		DISP_OFF		0x08	        //
#define		CLR_DISP		0x01    	//
#define		WRITE_0_DDRAM_ADDRESS	0x80
#define 	WRITE_40_DDRAM_ADDRESS	0xA8
#define		WRITE_DDRAM_ADDRESS	0x80
#define		WRITE_DDRAM		0x20

// Necessaire a cause d'un bug d'insight
int variableGlobalePourBSS;
int variableGlobalePourDATA=1;



void _E(void)
{
    bitset(P2OUT,E);		//toggle E for LCD
	delay(10);
	bitclr(P2OUT,E);
}

void SEND_CHAR (unsigned char d)
{
    int temp;
	delayx100us(5);                 //.5ms	
	temp = d & 0xf0;		//get upper nibble	
	LCD_Data &= 0x0f;
	LCD_Data |= temp;
	bitset(P2OUT,RS);     	        //set LCD to data mode
	_E();                           //toggle E for LCD
	temp = d & 0x0f;
	temp = temp << 4;               //get down nibble
	LCD_Data &= 0x0f;
	LCD_Data |= temp;
	bitset(P2OUT,RS);   	        //set LCD to data mode
	_E();                           //toggle E for LCD
}

void SEND_CMD (unsigned char e)
{
    int temp;
	delayx100us(10);                //10ms
	temp = e & 0xf0;		//get upper nibble	
	LCD_Data &= 0x0f;
	LCD_Data |= temp;               //send CMD to LCD
	bitclr(P2OUT,RS);     	        //set LCD to CMD mode
	_E();                           //toggle E for LCD
	temp = e & 0x0f;
	temp = temp << 4;               //get down nibble
	LCD_Data &= 0x0f;
	LCD_Data |= temp;
	bitclr(P2OUT,RS);   	        //set LCD to CMD mode
	_E();                           //toggle E for LCD
}





void initLCD(void)
{
    bitclr(P2OUT,RS);
	//OSTimeDly(DELAY_100ms);
	
    delayx100us(250);                   //Delay 100ms
    delayx100us(250);
    delayx100us(250);
    delayx100us(250);
    LCD_Data |= BIT4 | BIT5;            //D7-D4 = 0011
    LCD_Data &= ~BIT6 & ~BIT7;
    _E();                               //toggle E for LCD
    delayx100us(100);                   //10ms
	//OSTimeDly(DELAY_10ms);
    _E();                               //toggle E for LCD
    delayx100us(100);                   //10ms
	//OSTimeDly(DELAY_10ms);
    _E();                               //toggle E for LCD
    delayx100us(100);                   //10ms
	//OSTimeDly(DELAY_10ms);
    LCD_Data &= ~BIT4;
    _E();                               //toggle E for LCD

    SEND_CMD(DISP_ON);
    SEND_CMD(CLR_DISP);
    delayx100us(250);
    delayx100us(250);
    delayx100us(250);
    delayx100us(250);
	//OSTimeDly(DELAY_100ms);
}

void clearDisplay() 
{
    SEND_CMD(CLR_DISP);
    delayx100us(10);
}

void initDisplay(void)
{
  initLCD();
  clearDisplay();
}

int putcDisplay(char c)
{
	SEND_CHAR(c);
	return 0;
}

int lprintDisplay(char* format, int line)
{
	char* c = format;
	int idx = 0;
	if (line == FIRST_LINE)
	{
		SEND_CMD(WRITE_DDRAM_ADDRESS | 0x0);
		
	}
	else if (line == SECOND_LINE)
	{
		SEND_CMD(WRITE_DDRAM_ADDRESS | 0x40);
	}
	else
	{
		return -1;
	}
	//while(*c && *c != '\0') putcDisplay(*c++);
	while(idx < MAX_LINE_LENGHT && format[idx] != '\0') putcDisplay(format[idx++]);
	return 0;
	
}

int cprintDisplay(char c, int line, int pos)
{
	int address;
	address = line * 64 + pos; // 64 -> 16 char sur 4bit
	SEND_CMD(WRITE_DDRAM_ADDRESS | address);
	putcDisplay(c);
	return 0;
}

int printDisplay(char* format)
{
	int pos;
	char firstLine[MAX_LINE_LENGHT+1], secondLine[MAX_LINE_LENGHT+1];

	pos = 0;
	while(*format != '\n' && *format != '\0' && pos < MAX_LINE_LENGHT) {firstLine[pos] = *format++; pos++;}
	while(pos < MAX_LINE_LENGHT) {firstLine[pos] = ' '; pos++;}
	
	while(*format != '\0' && *format != '\n') format++;
	if (*format != '\0') format++; // saute le \n
	
	pos = 0;
	while(*format != '\0' && pos < MAX_LINE_LENGHT) {secondLine[pos] = *format++; pos++;}
	while(pos < MAX_LINE_LENGHT) {secondLine[pos] = ' '; pos++;}
	
	lprintDisplay(firstLine, FIRST_LINE);
	lprintDisplay(secondLine, SECOND_LINE);
	
	return 0;
}



